#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include "Task.hpp"
#include "Channel.hpp"

using work_t = std::function<void()>;

enum
{
	OK = 0,
	UsageError,
	PipeError,
	ForkError
};

class ProcessPool
{
public:
	ProcessPool(int n, work_t w) : processnum(n), work(w)
	{
	}
	// work_t work 回调方法
	int InitProcessPool()
	{
		// 2.创建指定个数的进程
		for (int i = 0; i < processnum; i++)
		{
			// 1.先创建管道
			int pipefd[2] = {0};
			int n = pipe(pipefd);
			if (n < 0)
				return PipeError;

			// 创建进程
			pid_t id = fork();
			if (id < 0)
				return ForkError;

			// 4.建立通信信道
			if (id == 0)
			{
				//关闭历史wfd
				for(auto &c : channels)
					c.Close(); 

				::close(pipefd[1]); // read
				// child
				dup2(pipefd[0], 0); //
				Worker();
				exit(0);
			}

			// father
			::close(pipefd[0]); // write
			channels.emplace_back(pipefd[1], id);
			// Channel ch(pipefd[1],id);
			// channels.push_back(ch);
		}
		return OK;
	}

	void DispatchTask()
	{
		int who = 0;
		// 2.派发任务
		int num = 5;
		while (num--)
		{
			// a.选择一个任务
			int task = tm.SelectTask();
			// b.选择一个子进程
			Channel &curr = channels[who++];
			who %= channels.size();

			std::cout << "#################" << std::endl;
			std::cout << "send " << task << "to" << curr.Name() << ",任务还剩: " << num << std::endl;
			std::cout << "#################" << std::endl;
			// c.派发任务
			curr.Send(task);

			sleep(1);
		}
	}

	void CleanProcessPool()
	{
		// verson1
		// for (auto &c : channels)
		// {
		// 	c.Close();
		// }

		// for (auto &c : channels)
		// {
		// 	pid_t rid = ::waitpid(c.Id(), nullptr, 0);
		// 	if (rid > 0)
		// 	{
		// 		std::cout << "child " << rid << "wait ... success" << std::endl;
		// 	}
		// }

		//  verson2
		// for(int i = channels.size()-1;i >= 0;i--)
		// {
		// 	channels[i].Close();
		// 	pid_t rid = ::waitpid(channels[i].Id(), nullptr, 0); //等待阻塞
		// 	if (rid > 0)
		// 	{
		// 		std::cout << "child " << rid << "wait ... success" << std::endl;
		// 	}
		// }

		// verson3
		for (auto &c : channels)
		{
			c.Close();
			pid_t rid = ::waitpid(c.Id(), nullptr, 0);
			if (rid > 0)
			{
				std::cout << "child " << rid << "wait ... success" << std::endl;
			}
		}
	}

	void Print()
	{
		for (auto &c : channels)
		{
			std::cout << c.Name() << std::endl;
		}
	}

private:
	std::vector<Channel> channels;
	int processnum;
	work_t work;
};
